package com.yunxi.core.service;

import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.yunxi.core.dao.BaseMapperPlus;
import com.yunxi.core.page.PageHelperPlus;
import com.yunxi.core.util.BeanTools;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


public class ServiceImplPlus<M extends BaseMapperPlus<T>, T> extends ServiceImpl<M, T> implements IServicePlus<T> {

    private static final Log logger = LogFactory.getLog(ServiceImplPlus.class);

    public Object getByMap(Map<String, Object> map) {

//        return SqlHelper.getObject(this.baseMapper.queryByList(map));
        return (T)this.getObject(this.baseMapper.queryByList(map));
    }

    @Override
    public PageInfo pageByVo(Object vo, Integer pageNum, Integer pageSize) {
        Map map = BeanTools.bean2map(vo);
        PageHelperPlus.startPage(pageNum,pageSize);
        List<Object> list = baseMapper.queryByList(map);
        PageInfo<Object> pageInfo = new PageInfo<Object>(list);
        return pageInfo;
    }

    @Override
    public List listByVo(Object vo) {
        return listBy(BeanTools.bean2map(vo));
    }

    @Override
    public Object getByVo(Object vo) {
        return (T)getByMap(BeanTools.bean2map(vo));
    }

    public List listBy(Map<String, Object> map) {
        List<Object> list = baseMapper.queryByList(map);
        return list;
    }

    public PageInfo pageByMap(Map<String, Object> map) {
        PageHelperPlus.startPage(map);
        List<Object> list = baseMapper.queryByList(map);
        PageInfo<Object> pageInfo = new PageInfo<Object>(list);
        return pageInfo;
    }

    public void removeByList(Collection<T> idList){
        if(idList!=null&&idList.size()>0){

            for(Iterator<T> it = idList.iterator(); it.hasNext();)
            {
                T entity = it.next();
                Class<?> cls = entity.getClass();
                TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
                if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
                    Object idVal = ReflectionKit.getMethodValue(cls, entity, tableInfo.getKeyProperty());
                    removeById((Serializable)idVal);
                } else {
                    throw ExceptionUtils.mpe("Error:  Can not execute. Could not find @TableId.");
                }
            }
        }
    }

    public void removeByListVo(List idList) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        if(idList!=null&&idList.size()>0){

            for(Iterator<Object> it = idList.iterator(); it.hasNext();)
            {
                Object entity = it.next();
                T o = currentModelClass().newInstance();
                //ConvertUtils.register(new DateConverter(null), java.util.Date.class);
                org.springframework.beans.BeanUtils.copyProperties(entity,o);
                Class<?> cls = o.getClass();
                TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
                if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
                    Object idVal = ReflectionKit.getMethodValue(cls, o, tableInfo.getKeyProperty());
                    removeById((Serializable)idVal);
                } else {
                    throw ExceptionUtils.mpe("Error:  Can not execute. Could not find @TableId.");
                }
            }
        }
    }

    public void updateByListVo(List idList) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        if(idList!=null&&idList.size()>0){

            for(Iterator<Object> it = idList.iterator(); it.hasNext();)
            {
                Object entity = it.next();
                T o = currentModelClass().newInstance();
                //ConvertUtils.register(new DateConverter(null), java.util.Date.class);
                org.springframework.beans.BeanUtils.copyProperties(entity,o);
                Class<?> cls = o.getClass();
                TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
                if (null != tableInfo && StringUtils.isNotEmpty(tableInfo.getKeyProperty())) {
                    //Object idVal = ReflectionKit.getMethodValue(cls, o, tableInfo.getKeyProperty());
                    saveOrUpdate(o);
                } else {
                    throw ExceptionUtils.mpe("Error:  Can not execute. Could not find @TableId.");
                }
            }
        }
    }

    public static <E> E getObject(List<E> list) {
        if(CollectionUtils.isNotEmpty(list)) {
            int size = list.size();
            if(size > 1) {
                logger.warn(String.format("Warn: execute Method There are  %s results.", new Object[]{Integer.valueOf(size)}));
            }

            return list.get(0);
        } else {
            return null;
        }
    }
}